home *** CD-ROM | disk | FTP | other *** search
- #include "screen.h"
- #define DEBUG(s) static char *___Xyz = s
-
- SCREEN *screen[NUMSCREENS], *current;
- void paint();
-
- /* utility routines -- assume that src and dst are word aligned */
-
- void quickzero(dst, nbytes)
- long *dst; long nbytes;
- {
- DEBUG("quickzero");
- unsigned leftover;
- char *foo;
-
- leftover = nbytes & 0x0f;
- nbytes = nbytes >> 4;
- while (nbytes-- > 0) {
- *dst++ = 0; *dst++ = 0;
- *dst++ = 0; *dst++ = 0;
- }
- foo = (char *)dst;
- while (leftover-- > 0)
- *foo++ = 0;
- }
-
- extern void normal_putch(), escy_putch();
-
- void
- init(v)
- SCREEN *v;
- {
- int i, j;
- extern void *malloc();
- char *foo, *data;
- DEBUG("init");
-
- v->maxx = 80;
- v->maxy = 25;
- v->cx = v->cy = 0;
- v->cwidth = 8; /* always 8 pixels wide */
- v->cheight = 8;
- v->planesiz = 80;
-
- v->linelen = v->planesiz * v->cheight;
- v->state = normal_putch;
- v->flags = FCURS;
- v->lastlineoff = (v->maxy-1) * v->linelen;
- v->lineoff = (long *)malloc(v->maxy * sizeof(long));
- v->lineoff[0] = 0;
- for (i = 1; i < v->maxy; i++) {
- v->lineoff[i] = v->lineoff[i-1] + v->linelen;
- }
-
- quickzero(v->base, (long)v->lastlineoff + v->linelen);
- }
-
- /*
- * PLACE(v, x, y): the address corresponding to the upper left hand corner of
- * the character at position (x,y) on screen v
- */
- static
- #ifdef __GNUC__
- inline
- #endif
- char *PLACE(v, x, y)
- SCREEN *v;
- int x, y;
- {
- char *place;
-
- place = x + v->base + v->lineoff[y];
-
- return place;
- }
-
- /*
- * paint(v, c, x, y): put character 'c' at position (x, y) on screen
- * v. It is assumed that x, y are proper coordinates!
- */
- extern char *my_font;
-
- void
- paint(v, c, x, y)
- SCREEN *v;
- int c, x, y;
- {
- DEBUG("paint");
- char *data, *place, d, doinverse;
- int i, j;
- short vplanesiz;
-
- data = (char *)(&my_font+2*(c&0x007f));
- place = PLACE(v, x, y);
- doinverse = (v->flags & FINVERSE) ? 0xff : 0;
-
- vplanesiz = v->planesiz;
-
- for (j = 8; j > 0; --j) {
- place[0] = *data++ ^ doinverse;
- place += vplanesiz;
- }
-
- }
-
- /*
- * gotoxy (v, x, y): move current cursor address of screen v to (x, y)
- * does nothing if (x,y) is illegal
- */
-
- void
- gotoxy(v, x, y)
- SCREEN *v;
- int x, y;
- {
- DEBUG("gotoxy");
- if (x >= v->maxx || y >= v->maxy || x < 0 || y < 0)
- return;
- v->cx = x;
- v->cy = y;
- }
-
- /*
- * clrline(v, r): clear line r of screen v
- */
-
- void
- clrline(v, r)
- SCREEN *v;
- int r;
- {
- DEBUG("clrline");
- long *dst;
- long nbytes;
-
- nbytes = v->linelen;
- dst = (long *)(v->base + (r * v->linelen));
-
- quickzero(dst, nbytes);
- }
-
- /*
- * clear(v): clear the whole screen v
- */
-
- void
- clear(v)
- SCREEN *v;
- {
- DEBUG("clear");
- long *dst;
- long nbytes;
-
- nbytes = v->lastlineoff + v->linelen;
- dst = (long *)v->base;
-
- quickzero(dst, nbytes);
- }
-
- /*
- * clrchar(v, x, y): clear the (x,y) position on screen v
- */
-
- void
- clrchar(v, x, y)
- SCREEN *v;
- int x, y;
- {
- DEBUG("clrchar");
- int i, j, planesiz;
- char *place;
-
- planesiz = v->planesiz;
-
- place = PLACE(v, x, y);
-
- for (j = 8; j > 0; --j) {
- *place = 0;
- place += planesiz;
- }
- }
-
- /*
- * clrfrom(v, x1, y1, x2, y2): clear screen v from position (x1,y1) to
- * position (x2, y2) inclusive. It is assumed that y2 >= y1.
- */
-
- void
- clrfrom(v, x1, y1, x2, y2)
- SCREEN *v;
- int x1,y1,x2,y2;
- {
- int i;
-
- DEBUG("clrfrom");
- for (i = x1; i < v->maxx; i++)
- clrchar(v, i, y1);
- if (y2 > y1) {
- for (i = 0; i <= x2; i++)
- clrchar(v, i, y2);
- for (i = y1+1; i < y2; i++)
- clrline(v, i);
- }
- }
-
- /*
- * delete_line(v, r): delete line r of screen v. The screen below this
- * line is scrolled up, and the bottom line is cleared.
- */
-
- #define scroll(v) delete_line(v, 0)
-
- void
- delete_line(v, r)
- SCREEN *v;
- int r;
- {
- DEBUG("delete_line");
- long *src, *dst, nbytes;
-
- if (r == 0)
- nbytes = v->lastlineoff;
- else
- nbytes = v->linelen * (v->maxy - (r+1));
-
- dst = (long *)(v->base + v->lineoff[r]);
- src = (long *)( ((long)dst) + v->linelen);
-
- quickmove(dst, src, nbytes);
-
- /* clear the last line */
-
- clrline(v, v->maxy - 1);
- }
-
- /*
- * insert_line(v, r): scroll all of the screen starting at line r down,
- * and then clear line r.
- */
-
- void
- insert_line(v, r)
- SCREEN *v;
- int r;
- {
- DEBUG("insert_line");
- long *src, *dst;
- int i, limit;
-
- limit = v->maxy - 1;
- for (i = limit-1; i >= r ; --i) {
- /* move line i to line i+1 */
- src = (long *)(v->base + v->lineoff[i]);
- dst = (long *)(v->base + v->lineoff[i+1]);
-
- quickmove(dst, src, (long)v->linelen);
- }
-
- /* clear line r */
- clrline(v, r);
- }
-
- /*
- * putesc(v, c): handle the control sequence ESC c
- */
-
- void
- putesc(v, c)
- SCREEN *v;
- int c;
- {
- DEBUG("putesc");
- int cx, cy;
-
- cx = v->cx; cy = v->cy;
-
- switch (c) {
- case 'A': /* cursor up */
- gotoxy(v, cx, cy-1);
- break;
- case 'B': /* cursor down */
- gotoxy(v, cx, cy+1);
- break;
- case 'C': /* cursor right */
- gotoxy(v, cx+1, cy);
- break;
- case 'D': /* cursor left */
- gotoxy(v, cx-1, cy);
- break;
- case 'E': /* clear home */
- clear(v);
- /* fall through... */
- case 'H': /* cursor home */
- gotoxy(v, 0, 0);
- break;
- case 'I': /* cursor up, insert line */
- if (cy == 0)
- insert_line(v, 0);
- else
- gotoxy(v, cx, cy-1);
- break;
- case 'J': /* clear below cursor */
- clrfrom(v, cx, cy, v->maxx-1, v->maxy-1);
- break;
- case 'K': /* clear remainder of line */
- clrfrom(v, cx, cy, v->maxx-1, cy);
- break;
- case 'L': /* insert a line */
- insert_line(v, cy);
- gotoxy(v, 0, cy);
- break;
- case 'M': /* delete line */
- delete_line(v, cy);
- gotoxy(v, 0, cy);
- break;
- case 'Y':
- v->state = escy_putch;
- return; /* YES, this should be 'return' */
-
- case 'd': /* clear to cursor position */
- clrfrom(v, 0, 0, cx, cy);
- break;
- case 'e': /* enable cursor */
- v->flags |= FCURS;
- flash_on(v);
- break;
- case 'f': /* cursor off */
- flash_off(v);
- v->flags &= ~FCURS;
- break;
- case 'j': /* save cursor position */
- v->savex = v->cx;
- v->savey = v->cy;
- break;
- case 'k': /* restore saved position */
- gotoxy(v, v->savex, v->savey);
- break;
- case 'l': /* clear line */
- clrline(v, cy);
- gotoxy(v, 0, cy);
- break;
- case 'o': /* clear from start of line to cursor */
- clrfrom(v, 0, cy, cx, cy);
- break;
- case 'p': /* reverse video on */
- v->flags |= FINVERSE;
- break;
- case 'q': /* reverse video off */
- v->flags &= ~FINVERSE;
- break;
- case 'v': /* wrap on */
- v->flags |= FWRAP;
- break;
- case 'w':
- v->flags &= ~FWRAP;
- break;
- }
- v->state = normal_putch;
- }
-
- /*
- * escy1_putch(v, c): for when an ESC Y + char has been seen
- */
- void
- escy1_putch(v, c)
- SCREEN *v;
- int c;
- {
- gotoxy(v, c - ' ', v->escy1 - ' ');
- v->state = normal_putch;
- }
-
- /*
- * escy_putch(v, c): for when an ESC Y has been seen
- */
- void
- escy_putch(v, c)
- SCREEN *v;
- int c;
- {
- v->escy1 = c;
- v->state = escy1_putch;
- }
-
- /*
- * normal_putch(v, c): put character 'c' on screen 'v'. This is the default
- * for when no escape, etc. is active
- */
-
- void
- normal_putch(v, c)
- SCREEN *v;
- int c;
- {
- DEBUG("normal_putch");
- int cx, cy;
- int state;
-
- cx = v->cx; cy = v->cy;
-
- /* control characters */
- if (c < ' ') {
- switch (c) {
- case '\r':
- gotoxy(v, 0, cy);
- return;
- case '\n':
- if (cy == v->maxy - 1)
- scroll(v);
- else
- gotoxy(v, cx, cy+1);
- return;
- case '\b':
- gotoxy(v, cx-1, cy);
- return;
- case '\007': /* BELL */
- Bconout(2, 7);
- return;
- case '\033': /* ESC */
- v->state = putesc;
- return;
- case '\t':
- state = 8 - ((v->cx & 7));
- while(state > 0) {
- normal_putch(v, ' ');
- state--;
- }
- return;
- default:
- return;
- }
- }
-
- paint(v, c, cx, cy);
- v->cx++;
- if (v->cx == v->maxx) {
- if (v->flags & FWRAP) {
- v->cx = 0;
- normal_putch(v, '\n');
- }
- else
- v->cx--;
- }
- }
-
- void
- put_ch(v, c)
- SCREEN *v;
- int c;
- {
- (*(v->state))(v, c & 0x00ff);
- }
-
- /* routines for flashing the cursor for screen v */
-
- static void
- flash(v)
- SCREEN *v;
- {
- char *place;
- int i, j;
- short vplanesiz;
- int x, y;
-
- vplanesiz = v->planesiz;
- x = v->cx; y = v->cy;
-
- place = PLACE(v, x, y);
-
- for (j = 8; j > 0; --j) {
- (*place)^= 0xff;
- place += vplanesiz;
- }
- }
-
- /* make sure the cursor is off */
-
- void
- flash_off(v)
- SCREEN *v;
- {
- if (v->flags & FFLASH) {
- v->flags ^= FFLASH;
- flash(v);
- }
- }
-
- /* make sure the cursor is on (if it's enabled, of course!) */
-
- void
- flash_on(v)
- SCREEN *v;
- {
- if (v->flags & FFLASH)
- return;
- if (v->flags & FCURS) {
- v->flags |= FFLASH;
- flash(v);
- }
- }
-